home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / pascal / totsrc.zip / TOTMENU.PAS < prev    next >
Pascal/Delphi Source File  |  1991-02-11  |  54KB  |  2,017 lines

  1. {               Copyright 1991 TechnoJock Software, Inc.               }
  2. {                          All Rights Reserved                         }
  3. {                         Restricted by License                        }
  4.  
  5. {                             Build # 1.00                             }
  6.  
  7. Unit totMENU;
  8. {$I TOTFLAGS.INC}
  9.  
  10. {
  11.  Development Notes:
  12. }
  13.  
  14. INTERFACE
  15.  
  16. uses DOS, CRT, 
  17.      totLOOK, totSYS, totINPUT, totFAST, totWIN, totSTR, totIO1, totLINK;
  18.  
  19. CONST
  20.    EscapeID = 65535;
  21.    LeftID   = 65534;
  22.    RightID  = 65533;
  23.    DriftID  = 65532;
  24.  
  25. TYPE
  26. BaseMenuPtr = ^BaseMenuOBJ;         
  27. MenuItemPtr = ^MenuItem;
  28. MenuItem = record
  29.    NextNode: MenuItemPtr;
  30.    TxtPtr: pointer;
  31.    MsgPtr: pointer;
  32.    HK: word;
  33.    ID: word;
  34.    Active: boolean;
  35.    SubMenu:  BaseMenuPtr;
  36. end;
  37.  
  38. pBaseMenuOBJ = ^BaseMenuOBJ;
  39. BaseMenuOBJ = object
  40.    vItemStack: MenuItemPtr;
  41.    vTotalItems: byte;
  42.    vActiveItem: byte;
  43.    vGap: byte;
  44.    vMsgX: byte;
  45.    vMsgY: byte;
  46.    vX: byte;
  47.    vY: byte;
  48.    vWidth: byte;
  49.    vLastKey: word;
  50.    vAllowEsc: boolean;
  51.    vUsedInPull: boolean;
  52.    vPickOff: boolean;
  53.    vSubActive: boolean;
  54.    vMenuHiHot: byte;
  55.    vMenuHiNorm: byte;
  56.    vMenuLoHot: byte;
  57.    vMenuLoNorm: byte;
  58.    vMenuOff: byte;
  59.    vHelpHook:  HelpProc;
  60.    vHelpKey: word;
  61.    vMsgVisible: boolean;
  62.    {methods...}
  63.    constructor Init;
  64.    procedure   AddFullItem(Txt:StrVisible; ID,HK:word; Msg:StrVisible; SubM:BaseMenuPtr);
  65.    procedure   AddItem(Txt:StrVisible);
  66.    procedure   SetTopic(Item:byte; Txt:StrVisible);
  67.    procedure   SetHK(Item:byte; HK:word);
  68.    procedure   SetMessage(Item:byte; Msg:StrVisible);
  69.    procedure   SetID(Item:byte; ID:word);
  70.    procedure   SetStatus(Item:byte; On:boolean);
  71.    procedure   SetSubMenu(Item:byte;SubMenu:BaseMenuPtr);
  72.    procedure   SetGap(G:byte);
  73.    procedure   SetActiveItem(Item:byte);
  74.    procedure   SetMessageXY(X,Y:byte);
  75.    procedure   SetMenuXY(X,Y:byte);
  76.    procedure   SetHelpKey(K:word);
  77.    procedure   SetHelpHook(Proc:HelpProc);
  78.    procedure   SetAllowEsc(On:boolean);
  79.    procedure   SetColors(HiHot,HiNorm,LoHot,LoNorm,Off:byte);
  80.    procedure   TurnPickOff;
  81.    function    GetAllowEsc: boolean;
  82.    function    GetText(Ptr:MenuItemPtr): StrVisible;
  83.    function    GetMessage(Ptr:MenuItemPtr): StrVisible;
  84.    function    GetID(Item:byte):word;
  85.    function    GetActiveItem: byte;
  86.    function    GetTotalItems: byte;
  87.    function    GetPickOff: boolean;
  88.    function    GetSubActive:boolean;
  89.    procedure   DisplayAllItems;
  90.    function    HotkeySelect(K:word): boolean;
  91.    procedure   ChangeActiveItem(New:byte);
  92.    function    FirstActiveItem: byte;
  93.    function    AddPre(Txt:StrVisible;Hi:boolean):StrVisible;
  94.    function    AddSuf(Txt:StrVisible;Hi:boolean):StrVisible;
  95.    function    ItemPtr(Item:byte): MenuItemPtr;
  96.    procedure   DisposeItems;
  97.    procedure   ChangeMessage(Item:byte; Hi:boolean);
  98.    function    LastKey: word;
  99.    function    GetHelpID: word;
  100.    function    ProcessKey(K:word; X,Y:byte):word;                VIRTUAL;
  101.    function    MenuZone(X,Y:byte):boolean;                       VIRTUAL;
  102.    procedure   SetForPull;                                       VIRTUAL;
  103.    function    TargetPick(X,Y:byte): byte;                       VIRTUAL;
  104.    procedure   DisplayItem(Item:byte;Hi,Msg:boolean);            VIRTUAL;
  105.    procedure   Remove;                                           VIRTUAL;
  106.    function    Activate: word;                                   VIRTUAL;
  107.    procedure   DrawEngine(eX,eY:byte);                           VIRTUAL;
  108.    procedure   HelpTask(ID:word);                                VIRTUAL;
  109.    destructor  Done;                                             VIRTUAL;
  110.    end; {BaseMenuOBJ}
  111.  
  112. pWinMenuOBJ = ^WinMenuOBJ;
  113. WinMenuOBJ = object (BaseMenuOBJ)
  114.    vStyle: byte;
  115.    vWinSaved: boolean;
  116.    vMenuBorder: byte;
  117.    vMenuTitle: byte;
  118.    vMenuIcons: byte;
  119.    {methods...}
  120.    constructor Init;
  121.    procedure   SetStyleTitle(St:byte;Tit:StrVisible);
  122.    procedure   Draw;
  123.    procedure   MoveUp;
  124.    procedure   MoveDown;
  125.    procedure   MoveHome;
  126.    procedure   MoveEnd;
  127.    function    MousePressed(X,Y:byte):boolean;
  128.    function    ProcessKey(K:word; X,Y:byte):word;                VIRTUAL; 
  129.    function    MenuZone(X,Y:byte):boolean;                       VIRTUAL;
  130.    procedure   SetForPull;                                       VIRTUAL;
  131.    function    TargetPick(X,Y:byte): byte;                       VIRTUAL;
  132.    procedure   DisplayItem(Item:byte;Hi,Msg:boolean);            VIRTUAL;
  133.    procedure   Remove;                                           VIRTUAL;
  134.    function    Activate: word;                                   VIRTUAL;
  135.    procedure   DrawEngine(eX,eY:byte);                           VIRTUAL;
  136.    function    Win: WinPtr;                                      VIRTUAL;
  137.    destructor  Done;                                             VIRTUAL;
  138. end; {WinMenuOBJ}
  139.  
  140. SubMenuPtr = ^MenuOBJ;
  141. pMenuOBJ = ^MenuOBJ;
  142. MenuOBJ = object (WinMenuOBJ)
  143.    vWin: WinPtr;
  144.    {methods...}
  145.    constructor Init;
  146.    function    Win: WinPtr;                                      VIRTUAL;
  147.    destructor  Done;                                             VIRTUAL;
  148. end; {MenuOBJ}
  149.  
  150. pMoveMenuOBJ = ^MoveMenuOBJ;
  151. MoveMenuOBJ = object (WinMenuOBJ)
  152.    vWin: MoveWinPtr;
  153.    {methods...}
  154.    constructor Init;
  155.    function    Win: WinPtr;                                      VIRTUAL;
  156.    destructor  Done;                                             VIRTUAL;
  157. end; {MoveMenuOBJ}
  158.  
  159. pBarMenuOBJ = ^BarMenuOBJ;
  160. BarMenuOBJ = object (BaseMenuOBJ)
  161.    {methods...}
  162.    constructor Init;
  163.    function    GetX(Item:byte): byte;
  164.    procedure   DisplayItem(Item:byte;Hi,Msg:boolean);            VIRTUAL;
  165.    procedure   DrawEngine(eX,eY:byte);                           VIRTUAL;
  166.    destructor  Done;                                             VIRTUAL;
  167. end; {BarMenuOBJ}
  168.  
  169. BarHotKeyPtr = ^BarHotKeyItem;
  170. BarHotKeyItem = record
  171.    HK:word;
  172.    ID:word;
  173.    NextNode: BarHotKeyPtr;
  174. end; {BarHotKeyRecord}
  175.  
  176. pLotusMenuOBJ = ^LotusMenuOBJ;
  177. LotusMenuOBJ = object (BarMenuOBJ)
  178.    vHKStack: BarHotKeyPtr;
  179.    vMenuBarVisible: boolean;
  180.    {methods...}
  181.    constructor Init;
  182.    procedure   Draw;
  183.    procedure   MoveLeft;
  184.    procedure   MoveRight;
  185.    procedure   MoveHome;
  186.    procedure   MoveEnd;
  187.    procedure   SetSpecialKey(HK:word;ID:word);
  188.    function    HotKeyID(HK:word):word;
  189.    function    GetHK(Item:byte):word;
  190.    procedure   DisposeSpecialKeys;
  191.    function    AltHKItem(K:word):word;
  192.    function    MenuKey(K:word; X,Y:byte): boolean;
  193.    function    MousePressed(X,Y:byte;var Choice:word):boolean;
  194.    function    Push(K:word; X,Y:byte): word;
  195.    function    ProcessKey(K:word; X,Y:byte):word;                VIRTUAL;
  196.    function    TargetPick(X,Y:byte): byte;                       VIRTUAL;
  197.    procedure   Remove;                                           VIRTUAL;
  198.    function    Activate: word;                                   VIRTUAL;
  199.    destructor  Done;                                             VIRTUAL;
  200. end; {LotusMenuOBJ}
  201.  
  202. pPullMenuOBJ = ^PullMenuOBJ;
  203. PullMenuOBJ = object (LotusMenuOBJ)
  204.    vMenuDown: boolean;
  205.    {methods...}
  206.    constructor Init;
  207.    procedure   MoveLeft;
  208.    procedure   MoveRight;
  209.    procedure   MoveHome;
  210.    procedure   MoveEnd;
  211.    function    MousePressed(X,Y:byte):boolean;
  212.    function    Push(K:word; X,Y:byte): word;
  213.    function    ProcessKey(K:word; X,Y:byte):word;                VIRTUAL;
  214.    function    Activate: word;                                   VIRTUAL;
  215.    destructor  Done;                                             VIRTUAL;
  216. end; {PullMenuOBJ}
  217.  
  218. SubMenuListPtr = ^SubMenuList;
  219. SubMenuList = record
  220.    SubMenu: SubMenuPTR;
  221.    NextMenu: SubMenuListPtr;
  222. end;
  223.  
  224. pEZPullOBJ = ^EZPullOBJ;
  225. EZPullOBJ = object
  226.    vTopBar: pPullMenuOBJ;
  227.    vSubMenuStack: SubMenuListPtr;
  228.    vListAssigned: boolean;
  229.    vTotalSubs: byte;
  230.    {methods...}
  231.    constructor Init;
  232.    function    Activate: word;                                  
  233.    procedure   BuildMenu;
  234.    function    MainMenu:pPullMenuOBJ;
  235.    function    SubMenu(MenuNumber: byte):SubMenuPtr; 
  236.    function    Push(K:word; X,Y:byte): word;
  237.    function    TotalStrings: word;                               VIRTUAL;
  238.    function    GetString(Item: word): string;                    VIRTUAL; 
  239.    destructor  Done;                                             VIRTUAL;
  240. end; {EZPullOBJ}
  241.  
  242. pEZPullArrayOBJ = ^EZPullArrayOBJ;
  243. EZPullArrayOBJ = object (EZPullOBJ)
  244.    vTotalItems: byte;
  245.    vArrayPtr: pointer;
  246.    vStrLength: byte;
  247.    {methods...}
  248.    constructor Init;
  249.    procedure   AssignList(var StrArray; Total:Longint; StrLength:byte);
  250.    function    TotalStrings: word;                               VIRTUAL;
  251.    function    GetString(Item: word): string;                    VIRTUAL;
  252.    destructor  Done;                                             VIRTUAL;
  253. end; {EZPullArrayOBJ}
  254.  
  255. pEZPullLinkOBJ = ^EZPullLinkOBJ;
  256. EZPullLinkOBJ = object (EZPullOBJ)
  257.    vLinkList: ^DLLOBJ;
  258.    {methods...}
  259.    constructor Init;
  260.    procedure   AssignList(var LinkList: DLLOBJ);
  261.    function    TotalStrings: word;                               VIRTUAL;
  262.    function    GetString(Item: word): string;                    VIRTUAL;
  263.    destructor  Done;                                             VIRTUAL;
  264. end; {EZPullLinkOBJ}
  265.  
  266. procedure menuINIT;
  267.  
  268. IMPLEMENTATION
  269. Const
  270.    EZSeparator:char = '"';
  271.    EZInActive: char = '_';
  272.    EZNewBarItem: char = '\';
  273.  
  274. procedure Error(Err:byte);
  275. {routine to display error}
  276. const
  277.    Header = 'totMENU error: ';
  278. var
  279.    Msg : string;
  280. begin
  281.    Case Err of
  282.    1: Msg := 'Not enough memory to create menu';
  283.    else  Msg := 'Unknown Error';
  284.    end; {case}
  285.    Writeln(Header,Msg);
  286.    halt;
  287. end; {Error}
  288. {|||||||||||||||||||||||||||||||||||||||||||||||}
  289. {                                               }
  290. {     B a s e M e n u O B J   M E T H O D S     }
  291. {                                               }
  292. {|||||||||||||||||||||||||||||||||||||||||||||||}
  293. {$I TOTMENU.INC}
  294. {|||||||||||||||||||||||||||||||||||||||||||||}
  295. {                                             }
  296. {     W i n M e n u O B J   M E T H O D S     }
  297. {                                             }
  298. {|||||||||||||||||||||||||||||||||||||||||||||}
  299. constructor WinMenuOBJ.Init;
  300. {}
  301. begin
  302.    BaseMenuOBJ.Init;
  303.    vWinSaved := false;
  304.    vStyle := 6;
  305.    vGap := 2;
  306. end; {WinMenuOBJ.Init}
  307.  
  308. procedure WinMenuOBJ.SetStyleTitle(St:byte;Tit:StrVisible);
  309. {}
  310. begin
  311.    vStyle := St;
  312.    Win^.SetTitle(Tit);
  313. end; {WinMenuOBJ.SetStyle}
  314.  
  315. procedure WinMenuOBJ.SetForPull;
  316. {}
  317. begin
  318.    SetStyleTitle(1,'');
  319.    SetGap(0);
  320.    Win^.SetClose(False);
  321.    vUsedInPull := true;
  322.    vMsgX := 11;
  323.    vMsgY := Monitor^.Depth;
  324. end; {WinMenuOBJ.SetForPull}
  325.  
  326. function WinMenuOBJ.Win: WinPtr;
  327. {abstract} begin end;
  328.  
  329. function WinMenuOBJ.MenuZone(X,Y:byte): boolean;
  330. {}
  331. var 
  332.    X1,Y1,X2,Y2,style: byte;
  333.    InZone: boolean;
  334. begin
  335.    if ItemPtr(vActiveItem)^.SubMenu <> nil then
  336.       InZone := ItemPtr(vActiveItem)^.SubMenu^.MenuZone(X,Y)
  337.    else
  338.       InZone := false;
  339.    if not InZone then
  340.    begin
  341.       Win^.GetSize(X1,Y1,X2,Y2,Style);
  342.       InZone := vWinsaved and (X >= X1) and (X <= X2) and (Y >= Y1) and (Y <= Y2);
  343.    end;
  344.    MenuZone := InZone;
  345. end; {WinMenuOBJ.MenuZone}
  346.  
  347. procedure WinMenuOBJ.DisplayItem(Item:byte;Hi,Msg:boolean);
  348. {}
  349. var               
  350.    Hot,Norm: byte;
  351.    Temp: MenuItemPtr;
  352.    Txt: StrVisible;
  353.    WinWasActive: boolean;
  354.  
  355.    procedure DrawLine(S:byte);
  356.    {}
  357.    const
  358.      Single: string[2] = '├┤';
  359.      Double: string[2] = '╞╡';
  360.    var
  361.      X1,Y1,X2,Y2,Style,Att: byte;
  362.      Ends: string[2];
  363.    begin
  364.      Win^.GetSize(X1,Y1,X2,Y2,Style);
  365.      if not (Style in [0,6]) then
  366.      begin
  367.         if S = 1 then
  368.            Ends := Single
  369.         else
  370.            Ends := Double;
  371.         Att := LookTOT^.MenuBor;
  372.         WinWasActive := Screen.WindowOff;
  373.         Y1 := Y1 + Item;
  374.         Screen.WriteAt(X1,Y1,Att,Ends[1]);
  375.         Screen.HorizLine(succ(X1),pred(X2),Y1,Att,Style);
  376.         Screen.WriteAt(X2,Y1,Att,Ends[2]);
  377.         Screen.WindowOn;
  378.      end;
  379.    end; {DrawLine}
  380.  
  381. begin
  382.    Temp := ItemPtr(Item);
  383.    if Temp = nil then
  384.       exit;
  385.    Txt := GetText(Temp);
  386.    if Txt = '-' then
  387.       DrawLine(1)
  388.    else if Txt = '=' then
  389.       DrawLine(2)
  390.    else
  391.    begin 
  392.       if Temp^.Active then
  393.       begin
  394.          if Hi then
  395.          begin
  396.             Hot := vMenuHiHot;
  397.             Norm := vMenuHiNorm;
  398.          end
  399.          else
  400.          begin
  401.             Hot := vMenuLoHot;
  402.             Norm := vMenuLoNorm;
  403.          end;
  404.       end
  405.       else
  406.       begin
  407.          Hot := vMenuoff;
  408.          Norm := vMenuoff;
  409.       end; 
  410.       Txt := AddPre(Txt,Hi);
  411.       if Temp^.Submenu <> nil then
  412.          Txt := Txt + #16;
  413.       Txt := AddSuf(Txt,Hi);
  414.       Screen.WriteHi(succ(vGap),Item,Hot,Norm,Txt);
  415.       if Msg then               {clear or display message}
  416.          ChangeMessage(Item,Hi);
  417.       if Hi then
  418.       begin
  419.          Screen.gotoxy(succ(vGap),Item);
  420.          vPickOff := false;
  421.       end;
  422.    end; 
  423. end; {WinMenuOBJ.DisplayItem}
  424.  
  425. procedure WinMenuOBJ.DrawEngine(eX,eY:byte);
  426. {}
  427. var 
  428.   Width,Depth: byte;
  429.   X,Y: byte;
  430. begin
  431.    if ItemPtr(vActiveItem)^.Active = false then
  432.       vActiveItem := FirstActiveItem; 
  433.    if not vWinSaved then
  434.    begin
  435.       vWinSaved := true;
  436.       Width := 2*vGap+vWidth+ ord(LookTOT^.ListLeftChar <> #0)
  437.                             + ord(LookTOT^.ListRightChar <> #0)
  438.                             + 2*ord(vStyle<> 0);
  439.       case vStyle of
  440.       0: Depth := vTotalItems;
  441.       6: Depth := vTotalItems + 4;
  442.       else Depth := vTotalItems + 2;
  443.       end; {case}
  444.       if eX = 0 then {center menu}
  445.          X := (Monitor^.Width - Width) div 2
  446.       else if eX + Width > Monitor^.Width then
  447.          X := Monitor^.Width - Width
  448.       else
  449.          X := eX;
  450.       if eY = 0 then {center menu}
  451.          Y := (Monitor^.Depth - Depth) div 2
  452.       else if eY + Depth > Monitor^.Depth then
  453.          Y := Monitor^.Depth - Depth
  454.       else
  455.          Y := eY;
  456.       Win^.SetSize(X,Y,pred(X)+Width,pred(Y)+Depth,vStyle);
  457.       Win^.Draw;
  458.       Screen.Clear(vMenuLoNorm,' ');
  459.       DisplayAllItems;
  460.    end
  461.    else if not vUsedInPull then
  462.    begin
  463.       Screen.Clear(vMenuLoNorm,' ');
  464.       DisplayAllItems;
  465.    end;
  466. end; {WinMenuOBJ.DrawEngine}
  467.  
  468. procedure WinMenuOBJ.Draw;
  469. {}
  470. begin
  471.    DrawEngine(vX,vY);
  472. end; {WinMenuOBJ.Draw}
  473.  
  474. procedure WinMenuOBJ.Remove;
  475. {}
  476. begin
  477.    if ItemPtr(vActiveItem)^.SubMenu <> nil then
  478.       ItemPtr(vActiveItem)^.SubMenu^.Remove;
  479.    ChangeMessage(vActiveItem,false);
  480.    vSubActive := false;
  481.    vPickOff := true;
  482.    Win^.Remove;
  483.    vWinSaved := false;
  484. end; {WinMenuOBJ.Remove}
  485.  
  486. procedure WinMenuOBJ.MoveUp;
  487. {}
  488. var 
  489.   NewItem: byte;
  490.   Txt: StrVisible;
  491. begin
  492.    NewItem := vActiveItem;
  493.    repeat
  494.       dec(NewItem);
  495.       if NewItem = 0 then
  496.          NewItem := vTotalItems;
  497.       Txt := GetText(ItemPtr(NewItem));
  498.    until (NewItem = vActiveItem)
  499.    or    (     (Txt <> '')
  500.            and (Txt <> '=')
  501.            and (Txt <> '-')
  502.            and (ItemPtr(NewItem)^.Active = true) );
  503.    ChangeActiveItem(NewItem);
  504. end; {WinMenuOBJ.MoveUp}
  505.  
  506. procedure WinMenuOBJ.MoveDown;
  507. {}
  508. var 
  509.   NewItem: byte;
  510.   Txt: StrVisible;
  511. begin
  512.    NewItem := vActiveItem;
  513.    repeat
  514.       inc(NewItem);
  515.       if NewItem > vTotalItems then
  516.          NewItem := 1;
  517.       Txt := GetText(ItemPtr(NewItem));
  518.    until (NewItem = vActiveItem)
  519.    or    (     (Txt <> '')
  520.            and (Txt <> '=')
  521.            and (Txt <> '-')
  522.            and (ItemPtr(NewItem)^.Active = true) );
  523.    ChangeActiveItem(NewItem);
  524. end; {WinMenuOBJ.MoveDown}
  525.  
  526. procedure WinMenuOBJ.MoveHome;
  527. {}
  528. var
  529.   NewItem: byte;
  530.   Txt: StrVisible;
  531. begin
  532.    if vActiveItem <> 1 then
  533.    begin
  534.       NewItem := 1;
  535.       Txt := GetText(ItemPtr(NewItem));
  536.       if (ItemPtr(NewItem)^.Active = false) 
  537.       or (Txt = '')
  538.       or (Txt = '=')
  539.       or (Txt = '-') then
  540.       begin
  541.          DisplayItem(vActiveItem,false,true);
  542.          vActiveItem := 1;
  543.          MoveDown;
  544.       end
  545.       else
  546.         ChangeActiveItem(NewItem);
  547.    end;
  548. end; {WinMenuOBJ.MoveHome}
  549.  
  550. procedure WinMenuOBJ.MoveEnd;
  551. {}
  552. var 
  553.   NewItem: byte;
  554.   Txt: StrVisible;
  555. begin
  556.    if vActiveItem <> vTotalItems then
  557.    begin
  558.       NewItem := vTotalItems;
  559.       Txt := GetText(ItemPtr(NewItem));
  560.       if (ItemPtr(NewItem)^.Active = false) 
  561.       or (Txt = '')
  562.       or (Txt = '=')
  563.       or (Txt = '-') then
  564.       begin
  565.          DisplayItem(vActiveItem,false,true);
  566.          vActiveItem := vTotalItems;
  567.          MoveUp;
  568.       end
  569.       else
  570.          ChangeActiveItem(NewItem);
  571.    end;
  572. end; {WinMenuOBJ.MoveEnd}
  573.  
  574. function WinMenuOBJ.TargetPick(X,Y:byte): byte;
  575. {}
  576. var 
  577.    X1,Y1,X2,Y2,Style: byte;
  578.    Temp: MenuItemPtr;
  579.    Txt: StrVisible;
  580. begin
  581.    TargetPick := 0;
  582.    Win^.GetSize(X1,Y1,X2,Y2,Style);
  583.    if ((Style=0) and (X in [X1..X2]) and (Y in [Y1..Y2]))
  584.    or ((Style=6) and (X in [succ(X1)..pred(X2)]) and (Y in [Y1+3..pred(Y2)]))
  585.    or ((Style <> 0) and (Style <> 6) and  (X in [succ(X1)..pred(X2)]) and (Y in [succ(Y1)..pred(Y2)]))
  586.    then
  587.    begin
  588.       case Style of 
  589.          0: dec(Y,pred(Y1));
  590.          6: dec(Y,(Y1+2));
  591.          else dec(Y,Y1);
  592.       end; {case}
  593.       Temp := ItemPtr(Y);
  594.       if (Temp <> nil) then
  595.       begin
  596.          Txt := GetText(Temp);
  597.          if (Temp^.Active = true) 
  598.          and (Txt <> '')
  599.          and (Txt <> '=')
  600.          and (Txt <> '-') then
  601.              TargetPick := Y;
  602.       end;
  603.    end;
  604. end; {WinMenuOBJ.TargetPick}
  605.  
  606. function WinMenuOBJ.MousePressed(X,Y:byte):boolean;
  607. {}
  608. var 
  609.    NewItem:byte;
  610.    Left,Center,Right : boolean;
  611.    X1,Y1,X2,Y2,style: byte;
  612. begin
  613.    NewItem := TargetPick(X,Y);
  614.    if NewItem <> 0 then
  615.    begin
  616.       ChangeActiveItem(NewItem);
  617.       Win^.GetSize(X1,Y1,X2,Y2,style);
  618.       repeat
  619.          Mouse.Status(Left,Center,Right,X,Y);
  620.          if Left then
  621.          begin
  622.             if vUsedInPull 
  623.             and ((X < X1) or (X > X2) or (Y < Y1) or (Y > Y2)) then
  624.             begin
  625.                MousePressed := false;
  626.                TurnPickOff;
  627.                exit;
  628.             end;
  629.             NewItem := TargetPick(X,Y);
  630.             if NewItem <> 0 then
  631.                ChangeActiveItem(NewItem);
  632.          end;
  633.       until not Left;
  634.       MousePressed := true;
  635.    end   
  636.    else
  637.       MousePressed := false;
  638. end; {WinMenuOBJ.MousePressed}
  639.  
  640. function WinMenuOBJ.ProcessKey(K:word; X,Y:byte):word;
  641. {}
  642. var
  643.    EscapeOn: boolean;
  644.    Finished: boolean;
  645.    HotKey: boolean;
  646.    Sub: BaseMenuPtr;
  647.    Choice: word;
  648.    SubX,SubY: byte;
  649.    X1,Y1,X2,Y2,style: byte;
  650. begin
  651.    Sub := ItemPtr(vActiveItem)^.SubMenu;
  652.    if (Sub <> nil) and vSubActive then
  653.    begin
  654.       Choice := Sub^.ProcessKey(K,X,Y);
  655.       if (Choice = DriftID) and vUsedInPull then
  656.       begin
  657.          Mouse.Location(X,Y);
  658.          Win^.GetSize(X1,Y1,X2,Y2,style);
  659.          if (X >= X1) and (X <= X2) and (Y >= Y1) and (Y <= Y2) then
  660.             Choice := EscapeID;
  661.       end;
  662.       if (Choice = EscapeID) then
  663.       begin
  664.          Choice := 0;
  665.          Sub^.Remove;
  666.          vSubActive := false;
  667.       end;
  668.    end
  669.    else
  670.    begin
  671.       Finished := false; {assume not finished}
  672.       HotKey := false;
  673.       Choice := 0;
  674.       if HotKeySelect(K) then
  675.          HotKey := true
  676.       else
  677.       begin
  678.          if K = vHelpKey then
  679.             HelpTask(GetID(vActiveItem))
  680.          else
  681.             case K of
  682.                600,
  683.                27: if vAllowEsc then
  684.                       Finished:= true;
  685.                13: Finished := true;
  686.                513: begin
  687.                   if vUsedInPull then
  688.                   begin
  689.                      Win^.GetSize(X1,Y1,X2,Y2,style);
  690.                      if (X < X1) or (X > X2) or (Y < Y1) or (Y > Y2) then
  691.                      begin
  692.                         Choice := DriftID;
  693.                         TurnPickOff;
  694.                      end
  695.                      else
  696.                         Finished := MousePressed(X,Y);
  697.                   end
  698.                   else
  699.                      Finished := MousePressed(X,Y);
  700.                end;
  701.                328: MoveUp;
  702.                336: MoveDown;
  703.                327: MoveHome;
  704.                335: MoveEnd;
  705.                331: if vUsedinPull then
  706.                        Choice := LeftID;
  707.                333: if vUsedinPull then
  708.                        Choice := RightID;
  709.             end; {case}
  710.       end;
  711.       if Hotkey or (((K = 13) or (K=513)) and Finished) then
  712.       begin
  713.          Sub := ItemPtr(vActiveItem)^.SubMenu;
  714.          if Sub <> Nil then
  715.          begin
  716.             EscapeOn := Sub^.GetAllowEsc;
  717.             if not EscapeOn then
  718.                Sub^.SetAllowEsc(true);
  719.             SubX := succ(lo(windmin))+Screen.WhereX;
  720.             SubY := succ(system.hi(windmin))+Screen.WhereY;
  721.             if not vUsedInPull then
  722.             begin
  723.                inc(SubX,10);
  724.                inc(SubY,2);
  725.             end;
  726.             ChangeMessage(vActiveItem,false);
  727.             Sub^.DrawEngine(SubX,SubY);
  728.             if vUsedInPull then
  729.                vSubActive := true
  730.             else
  731.             begin
  732.                Choice := Sub^.Activate;
  733.                Sub^.Remove;
  734.             end;
  735.             if not EscapeOn then
  736.                Sub^.SetAllowEsc(false);
  737.          end
  738.          else
  739.          begin
  740.             Choice := GetID(vActiveItem);
  741.             if Choice = 0 then
  742.                Choice := vActiveItem;
  743.          end;
  744.       end 
  745.       else if ((K = 27) or (K = 600)) and (Finished) then
  746.          Choice := EscapeID;
  747.    end;
  748.    ProcessKey := Choice; 
  749. end; {WinMenuOBJ.ProcessKey}
  750.  
  751. function WinMenuOBJ.Activate: word;
  752. {}
  753. var
  754.   K: word;
  755.   X,Y: byte;
  756.   Choice: word;
  757. begin
  758.    if not vWinSaved then
  759.       Draw
  760.    else
  761.       ChangeMessage(vActiveItem,true);
  762.    if Monitor^.ColorOn then
  763.       Screen.CursOff;
  764.    repeat
  765.       with Key do
  766.       begin
  767.          GetInput;
  768.          K := LastKey;
  769.          X := LastX;
  770.          Y := LastY;
  771.       end;
  772.       Win^.WinKey(K,X,Y);
  773.       Choice := ProcessKey(K,X,Y);
  774.    until (Choice <> 0);
  775.    if Choice = EscapeID then
  776.       Activate := 0
  777.    else
  778.       Activate := Choice;
  779.    ChangeMessage(vActiveItem,false);
  780.    vLastKey := Key.LastKey;
  781. end; {WinMenuOBJ.Activate}
  782.  
  783. destructor WinMenuOBJ.Done;
  784. {}
  785. begin
  786.    BaseMenuOBJ.Done;
  787. end; {WinMenuOBJ.Done}
  788. {|||||||||||||||||||||||||||||||||||||||}
  789. {                                       }
  790. {     M e n u O B J   M E T H O D S     }
  791. {                                       }
  792. {|||||||||||||||||||||||||||||||||||||||}
  793. constructor MenuOBJ.Init;
  794. {}
  795. begin
  796.    WinMenuOBJ.Init;
  797.    New(vWin,Init);
  798.    vWin^.SetTitle('Menu');
  799.    with LookTOT^ do
  800.       vWin^.SetColors(MenuBor, MenuloNorm, MenuTit, MenuIcon);
  801. end; {MenuOBJ.Init}
  802.  
  803. function MenuOBJ.Win: WinPtr;
  804. {}
  805. begin
  806.    Win := vWin;
  807. end; {MenuOBJ.Win}
  808.  
  809. destructor MenuOBJ.Done;
  810. {}
  811. begin
  812.    WinMenuOBJ.Done;
  813.    Dispose(vWin,Done);
  814. end; {MenuOBJ.Done}
  815. {|||||||||||||||||||||||||||||||||||||||||||||||}
  816. {                                               }
  817. {     M o v e M e n u O B J   M E T H O D S     }
  818. {                                               }
  819. {|||||||||||||||||||||||||||||||||||||||||||||||}
  820. constructor MoveMenuOBJ.Init;
  821. {}
  822. begin
  823.    WinMenuOBJ.Init;
  824.    New(vWin,Init);
  825.    vWin^.SetTitle('Menu');
  826.    vWin^.SetTitle('Menu');
  827.    with LookTOT^ do
  828.       vWin^.SetColors(MenuBor, MenuloNorm, MenuTit, MenuIcon);
  829. end; {MoveMenuOBJ.Init}
  830.  
  831. function MoveMenuOBJ.Win: WinPtr;
  832. {}
  833. begin
  834.    Win := vWin;
  835. end; {MoveMenuOBJ.Win}
  836.  
  837. destructor MoveMenuOBJ.Done;
  838. {}
  839. begin
  840.    WinMenuOBJ.Done;
  841.    Dispose(vWin,Done);
  842. end; {MoveMenuOBJ.Done}
  843. {|||||||||||||||||||||||||||||||||||||||||||||}
  844. {                                             }
  845. {     B a r M e n u O B J   M E T H O D S     }
  846. {                                             }
  847. {|||||||||||||||||||||||||||||||||||||||||||||}
  848. constructor BarMenuOBJ.Init;
  849. {}
  850. begin
  851.    BaseMenuOBJ.Init;
  852.    vX := 1;
  853.    vY := 1;
  854.    vGap := 0;
  855. end; {BarMenuOBJ.Init}
  856.  
  857. function BarMenuOBJ.GetX(Item:byte): byte;
  858. {}
  859. var 
  860.    I : integer;
  861.    X : byte;
  862. begin
  863.    if Item = 1 then
  864.       GetX := vX
  865.    else
  866.    begin
  867.       X := vX + pred(Item)*vGap;
  868.       for I := 1 to pred(Item) do
  869.          inc(X,length(strip('A',Screen.HiMarker,GetText(ItemPtr(I)))));
  870.       GetX := X;
  871.    end;
  872. end; {BarMenuOBJ.GetX}
  873.  
  874. procedure BarMenuOBJ.DisplayItem(Item:byte;Hi,Msg:boolean);
  875. {}
  876. var
  877.    Hot,Norm: byte;
  878.    X: byte;
  879.    Temp: MenuItemPtr;
  880.    Txt: StrVisible;
  881.    WinWasActive: boolean;
  882. begin
  883.    WinWasActive := Screen.WindowOff;
  884.    Temp := ItemPtr(Item);
  885.    if Temp^.Active then
  886.       begin
  887.          if Hi then
  888.          begin
  889.             Hot := vMenuHiHot;
  890.             Norm := vMenuHiNorm;
  891.          end
  892.          else
  893.          begin
  894.             Hot := vMenuLoHot;
  895.             Norm := vMenuLoNorm;
  896.          end;
  897.       end
  898.       else
  899.       begin
  900.          Hot := vMenuoff;
  901.          Norm := vMenuoff;
  902.       end;
  903.    Txt := GetText(Temp);
  904.    Txt := AddPre(Txt,Hi);
  905.    Txt := AddSuf(Txt,Hi);
  906.    X := GetX(Item);
  907.    Screen.WriteHi(X,vY,Hot,Norm,Txt);
  908.    if Msg then               {clear or display message}
  909.       ChangeMessage(Item,Hi);
  910.    if WinWasActive then
  911.       Screen.WindowOn;
  912.    if Hi then
  913.       Screen.gotoxy(X,vY);
  914. end; {BarMenuOBJ.DisplayItem}
  915.  
  916. procedure BarMenuOBJ.DrawEngine(eX,eY:byte); 
  917. {}
  918. begin
  919.    Screen.SetWinIgnore(true);
  920.    Screen.PartClear(vX,vY,GetX(vTotalItems)+
  921.                           length(strip('A',Screen.HiMarker,GetText(ItemPtr(vTotalItems)))),
  922.                     vY,LookTOT^.MenuLoNorm,' ');
  923.    Screen.SetWinIgnore(false);
  924.    DisplayAllItems;
  925. end; {BarMenuOBJ.DrawEngine}
  926.  
  927. destructor BarMenuOBJ.Done;
  928. {}
  929. begin
  930.    BaseMenuOBJ.Done;
  931. end; {BarMenuOBJ.Done}
  932. {|||||||||||||||||||||||||||||||||||||||||||||||||}
  933. {                                                 }
  934. {     L o t u s M e n u O B J   M E T H O D S     }
  935. {                                                 }
  936. {|||||||||||||||||||||||||||||||||||||||||||||||||}
  937. constructor LotusMenuOBJ.Init;
  938. {}
  939. begin
  940.    BarMenuOBJ.Init;
  941.    vHKStack := nil;
  942.    vMsgX := 1;
  943.    vMsgY := 2;
  944.    vMenuBarVisible := false;
  945. end; {LotusMenuOBJ.Init}
  946.  
  947. procedure LotusMenuOBJ.Draw;
  948. {}
  949. var I: integer;
  950. begin
  951.    vMenuBarVisible := true;
  952.    Screen.PartClear(vX,vY,GetX(vTotalItems)+
  953.                     length(strip('A',Screen.HiMarker,GetText(ItemPtr(vTotalItems)))),
  954.                     vY,LookTOT^.MenuLoNorm,' ');
  955.    for I := 1 to vTotalItems do
  956.        DisplayItem(I,false,false);
  957. end; {LotusMenuOBJ.Draw}
  958.  
  959. procedure LotusMenuOBJ.SetSpecialKey(HK:word;ID:word);
  960. {}
  961. var Temp: BarHotKeyPtr;
  962. begin
  963.    if MemAvail >= sizeof(vHKStack^) then
  964.    begin
  965.       if vHKStack = nil then
  966.       begin
  967.          getmem(vHkStack,sizeof(vHKStack^));
  968.          Temp := vHKStack;
  969.       end
  970.       else
  971.       begin
  972.          Temp := vHKStack;
  973.          while Temp^.NextNode <> nil do
  974.              Temp := Temp^.NextNode;
  975.          getmem(Temp^.NextNode,sizeof(vHKStack^));
  976.          Temp := Temp^.NextNode;
  977.       end;
  978.       Temp^.HK := HK;
  979.       Temp^.ID := ID;
  980.       Temp^.NextNode := nil;
  981.    end;
  982. end; {LotusMenuOBJ.SetSpecialKey}
  983.  
  984. function LotusMenuOBJ.HotKeyID(HK:word):word;
  985. {}
  986. var Temp: BarHotKeyPtr;
  987. begin
  988.    Temp := vHKStack;
  989.    while (Temp <> nil) and (HK <> Temp^.HK) do
  990.       Temp := Temp^.NextNode;
  991.    if Temp = nil then
  992.       HotKeyID := 0 
  993.    else
  994.       HotKeyID := Temp^.ID;
  995. end; {LotusMenuOBJ.HotKeyID}
  996.  
  997. function LotusMenuOBJ.GetHK(Item:byte):word;
  998. {}
  999. var Temp: MenuItemPtr;
  1000. begin
  1001.    Temp := ItemPtr(Item);
  1002.    if Temp <> nil then
  1003.       GetHK := Temp^.HK
  1004.    else
  1005.       GetHK := 0;
  1006. end; {LotusMenuOBJ.GetHK}
  1007.  
  1008. function LotusMenuOBJ.AltHKItem(K:word):word;
  1009. {}
  1010. var
  1011.   I : integer;
  1012. begin
  1013.    I := 1;
  1014.    if (K >= 97) and (K <= 122) then
  1015.       dec(K,32);
  1016.    while (I <= vTotalItems) and (AltKey(GetHK(I)) <> K) do
  1017.      inc(I);
  1018.    if (I > vTotalItems) or (ItemPtr(I)^.Active = false) then
  1019.       AltHKItem := 0
  1020.    else
  1021.       AltHKItem := I;
  1022. end; {LotusMenuOBJ.AltHKItem}
  1023.  
  1024. function LotusMenuOBJ.MenuKey(K:word; X,Y:byte): boolean;
  1025. {returns true if the key is recognized by the
  1026.  menu as a hotkey}
  1027. var Temp: word;
  1028. begin
  1029.    if (K = 513) and (TargetPick(X,Y) > 0) then
  1030.       MenuKey := true
  1031.    else
  1032.    begin
  1033.       Temp := AltHkItem(K);
  1034.       if Temp = 0 then
  1035.          Temp := HotKeyID(K);
  1036.       Menukey := (Temp <> 0);
  1037.    end;
  1038. end; {LotusMenuOBJ.MenuKey}
  1039.  
  1040. procedure LotusMenuOBJ.Remove;                 
  1041. {}
  1042. begin
  1043.    vMenuBarVisible := false;
  1044.    Screen.ClearText(vX,vY,Monitor^.Width,vY);
  1045.    ChangeMessage(vActiveItem,false);
  1046. end; {LotusMenuOBJ.Remove}
  1047.  
  1048. procedure LotusMenuOBJ.MoveLeft;
  1049. {}
  1050. var NewItem: byte;
  1051. begin
  1052.    NewItem := vActiveItem;
  1053.    repeat
  1054.       dec(NewItem);
  1055.       if NewItem < 1 then
  1056.          NewItem := vTotalItems;
  1057.    until (ItemPtr(NewItem)^.Active = true)
  1058.    or (NewItem = vActiveItem);
  1059.    ChangeActiveItem(NewItem);
  1060. end; {LotusMenuOBJ.MoveLeft}
  1061.  
  1062. procedure LotusMenuOBJ.MoveRight;
  1063. {}
  1064. var NewItem: byte;
  1065. begin
  1066.    NewItem := vActiveItem;
  1067.    repeat
  1068.       inc(NewItem);
  1069.       if NewItem > vTotalItems then
  1070.          NewItem := 1;
  1071.    until (ItemPtr(NewItem)^.Active = true)
  1072.    or (NewItem = vActiveItem);
  1073.    ChangeActiveItem(NewItem);
  1074. end; {LotusMenuOBJ.MoveRight}
  1075.  
  1076. procedure LotusMenuOBJ.MoveHome;
  1077. {}
  1078. var NewItem: byte;
  1079. begin
  1080.    if vActiveItem <> 1 then
  1081.    begin
  1082.       NewItem := 1;
  1083.       if (ItemPtr(NewItem)^.Active = false) then
  1084.       begin
  1085.          DisplayItem(vActiveItem,false,true);
  1086.          vActiveItem := 1;
  1087.          MoveRight;
  1088.       end
  1089.       else
  1090.          ChangeActiveItem(NewItem);
  1091.    end;
  1092. end; {LotusMenuOBJ.MoveHome}
  1093.  
  1094. procedure LotusMenuOBJ.MoveEnd;
  1095. {}
  1096. var NewItem: byte;
  1097. begin
  1098.    if vActiveItem <> vTotalItems then
  1099.    begin
  1100.       NewItem := vTotalItems;
  1101.       if (ItemPtr(NewItem)^.Active = false) then
  1102.       begin
  1103.          DisplayItem(vActiveItem,false,true);
  1104.          vActiveItem := vTotalItems;
  1105.          MoveLeft;
  1106.       end
  1107.       else
  1108.          ChangeActiveItem(NewItem);
  1109.    end;
  1110. end; {LotusMenuOBJ.MoveEnd}
  1111.                        
  1112. function LotusMenuOBJ.TargetPick(X,Y:byte): byte;
  1113. {}
  1114. var I : integer;
  1115. begin
  1116.    TargetPick := 0;
  1117.    if (Y = vY) and (X >= vX) then {at least on right line}
  1118.    begin
  1119.       I := 0;
  1120.       while I < vTotalItems do
  1121.       begin
  1122.          inc(I);
  1123.          if X <= GetX(I) + length(strip('A',Screen.HiMarker,GetText(ItemPtr(I)))) then
  1124.          begin
  1125.             TargetPick := I;
  1126.             exit;
  1127.          end;   
  1128.       end;
  1129.    end;
  1130. end; {LotusMenuOBJ.TargetPick}
  1131.  
  1132. function LotusMenuOBJ.MousePressed(X,Y:byte;var Choice:word):boolean;
  1133. {}
  1134. var 
  1135.   NewItem:byte;
  1136.   Left,Center,Right : boolean;
  1137.   Cleared: boolean;
  1138. begin
  1139.    NewItem := TargetPick(X,Y);
  1140.    if NewItem <> 0 then
  1141.    begin
  1142.       ChangeActiveItem(NewItem);
  1143.       Cleared := false;
  1144.       repeat
  1145.          Mouse.Status(Left,Center,Right,X,Y);
  1146.          if Left then
  1147.          begin
  1148.             NewItem := TargetPick(X,Y);
  1149.             if NewItem <> 0 then
  1150.             begin
  1151.                if (NewItem = vActiveItem) and cleared then
  1152.                    DisplayItem(vActiveItem,true,true)
  1153.                else
  1154.                   ChangeActiveItem(NewItem);
  1155.                Cleared := false;
  1156.             end
  1157.             else if not Cleared then
  1158.             begin
  1159.                DisplayItem(vActiveItem,false,true);
  1160.                Cleared := true;
  1161.             end;
  1162.          end;
  1163.       until not Left;
  1164.       if TargetPick(X,Y) <> 0 then
  1165.          MousePressed := true
  1166.       else
  1167.       begin
  1168.          MousePressed := false;
  1169.          Choice := DriftID
  1170.       end;
  1171.    end   
  1172.    else
  1173.       MousePressed := false;
  1174. end; {LotusMenuOBJ.MousePressed}
  1175.  
  1176. function LotusMenuOBJ.ProcessKey(K:word; X,Y:byte):word;
  1177. {}
  1178. var
  1179.    EscapeOn: boolean;
  1180.    Finished: boolean;
  1181.    HotKey: boolean;
  1182.    Sub: BaseMenuPtr;
  1183.    Choice: word;
  1184. begin
  1185.    Finished := false; {assume not finished}
  1186.    HotKey := false;
  1187.    Choice := AltHKItem(K);
  1188.    if Choice = 0 then
  1189.    begin
  1190.       if HotKeySelect(K) then
  1191.          HotKey := true
  1192.       else
  1193.       begin
  1194.          if K = 513 then
  1195.             Finished := MousePressed(X,Y,Choice)
  1196.          else if K = vHelpKey then
  1197.             HelpTask(GetID(vActiveItem))
  1198.          else
  1199.             case K of
  1200.                600,
  1201.                27: if vAllowEsc then
  1202.                       Finished:= true;
  1203.                13: Finished := true;
  1204.                331: MoveLeft;
  1205.                333: MoveRight;
  1206.                327: MoveHome;
  1207.                335: MoveEnd;
  1208.             end; {case}
  1209.       end;
  1210.       if Hotkey or (((K = 13) or (K=513)) and Finished) then
  1211.       begin
  1212.          Sub := ItemPtr(vActiveItem)^.SubMenu;
  1213.          if Sub <> Nil then
  1214.          begin
  1215.             EscapeOn := Sub^.GetAllowEsc;
  1216.             if not EscapeOn then
  1217.                Sub^.SetAllowEsc(true);
  1218.             ChangeMessage(vActiveItem,false);
  1219.             Sub^.DrawEngine(succ(lo(windmin))+Screen.WhereX,
  1220.                             succ(system.hi(windmin))+Screen.WhereY);
  1221.             Choice := Sub^.Activate;
  1222.             Sub^.Remove;
  1223.             if Choice = 0 then
  1224.                DrawEngine(0,0);
  1225.             if not EscapeOn then
  1226.                Sub^.SetAllowEsc(false);
  1227.          end
  1228.          else
  1229.          begin
  1230.             Choice := GetID(vActiveItem);
  1231.             if Choice = 0 then
  1232.                Choice := vActiveItem;
  1233.          end;
  1234.       end 
  1235.       else if ((K = 27) or (K = 600)) and (Finished) then
  1236.          Choice := EscapeID;
  1237.    end;
  1238.    ProcessKey := Choice; 
  1239. end; {LotusMenuOBJ.ProcessKey}
  1240.  
  1241. function LotusMenuOBJ.Activate: word;         
  1242. {}
  1243. begin
  1244.    Activate := Push(0,0,0);
  1245. end; {LotusMenuOBJ.Activate}
  1246.  
  1247. function LotusMenuOBJ.Push(K:word; X,Y: byte): word;         
  1248. {}
  1249. var
  1250.   Choice: word;
  1251.   FirstIteration,
  1252.   MVisible: boolean;
  1253.   CX,CY,CT,CB: byte;
  1254. begin
  1255.    MVisible := Mouse.Visible;
  1256.    if Monitor^.ColorOn then
  1257.       with Screen do
  1258.       begin
  1259.          CursSave;
  1260.          CX := WhereX;
  1261.          CY := WhereY;
  1262.          CT := CursTop;
  1263.          CB := CursBot;
  1264.          CursOff;
  1265.       end;
  1266.    DrawEngine(0,0);
  1267.    if not MVisible then
  1268.       Mouse.Show;
  1269.    FirstIteration := true;
  1270.    repeat
  1271.       if (FirstIteration = false) or ((K=0) and (X=0) and (Y=0)) then
  1272.          with Key do
  1273.          begin
  1274.             GetInput;
  1275.             K := LastKey;
  1276.             X := LastX;
  1277.             Y := LastY;
  1278.          end;
  1279.          Choice := ProcessKey(K,X,Y);
  1280.       FirstIteration := false;
  1281.    until (Choice <> 0);
  1282.    if Choice = EscapeID then
  1283.       Push := 0
  1284.    else
  1285.       Push := Choice;
  1286.    DisplayItem(vActiveItem,false,true);
  1287.    vLastKey := Key.LastKey;
  1288.    if not MVisible then
  1289.       Mouse.Hide;
  1290.    if Monitor^.ColorOn then
  1291.       with Screen do
  1292.       begin
  1293.          GotoXY(CX,CY);
  1294.          CursSize(CT,CB);
  1295.       end;
  1296. end; {LotusMenuOBJ.Push}
  1297.  
  1298. procedure LotusMenuOBJ.DisposeSpecialKeys;
  1299. {}
  1300. var Temp1, Temp2:BarHotKeyPtr;
  1301. begin
  1302.    if vHKStack <> nil then
  1303.    begin
  1304.       Temp1 := vHkStack;
  1305.       Temp2 := vHkStack;
  1306.       while Temp2 <> nil do
  1307.       begin
  1308.           Temp1 := Temp2;
  1309.           Temp2 := Temp2^.NextNode;
  1310.           freemem(Temp1,sizeof(Temp1^));
  1311.       end; 
  1312.       vHKStack := nil;
  1313.    end;
  1314. end; {LotusMenuOBJ.DisposeSpecialKeys}
  1315.  
  1316. destructor LotusMenuOBJ.Done;
  1317. {}
  1318. begin
  1319.    BarMenuOBJ.Done;
  1320.    DisposeSpecialKeys;
  1321. end; {LotusMenuOBJ.Done}
  1322. {|||||||||||||||||||||||||||||||||||||||||||||||}
  1323. {                                               }
  1324. {     P u l l M e n u O B J   M E T H O D S     }
  1325. {                                               }
  1326. {|||||||||||||||||||||||||||||||||||||||||||||||}
  1327. constructor PullMenuOBJ.Init;
  1328. {}
  1329. begin
  1330.    LotusMenuOBJ.Init;
  1331.    vMenuDown := false;
  1332.    vX := 2;
  1333.    vY := 1;
  1334.    vMsgX := 11;
  1335.    vMsgY := Monitor^.Depth;
  1336. end; {PullMenuOBJ.Init}
  1337.  
  1338. procedure PullMenuOBJ.MoveLeft;
  1339. {}
  1340. var Sub: BaseMenuPtr;
  1341. begin
  1342.    Sub := ItemPtr(vActiveItem)^.SubMenu;
  1343.    if vMenuDown and (Sub <> nil) then
  1344.       Sub^.Remove;
  1345.    LotusMenuOBJ.MoveLeft;
  1346. end; {PullMenuOBJ.MoveLeft}
  1347.  
  1348. procedure PullMenuOBJ.MoveRight;
  1349. {}
  1350. var Sub: BaseMenuPtr;
  1351. begin
  1352.    Sub := ItemPtr(vActiveItem)^.SubMenu;
  1353.    if vMenuDown and (Sub <> nil) then
  1354.       Sub^.Remove;
  1355.    LotusMenuOBJ.MoveRight;
  1356. end; {PullMenuOBJ.MoveRight}
  1357.  
  1358. procedure PullMenuOBJ.MoveHome;
  1359. {}
  1360. var Sub: BaseMenuPtr;
  1361. begin
  1362.    Sub := ItemPtr(vActiveItem)^.SubMenu;
  1363.    if vMenuDown and (Sub <> nil) then
  1364.       Sub^.Remove;
  1365.    LotusMenuOBJ.MoveHome;
  1366. end; {PullMenuOBJ.MoveHome}
  1367.  
  1368. procedure PullMenuOBJ.MoveEnd;
  1369. {}
  1370. var Sub: BaseMenuPtr;
  1371. begin
  1372.    Sub := ItemPtr(vActiveItem)^.SubMenu;
  1373.    if vMenuDown and (Sub <> nil) then
  1374.       Sub^.Remove;
  1375.    LotusMenuOBJ.MoveEnd;
  1376. end; {PullMenuOBJ.MoveEnd}
  1377.  
  1378. function PullMenuOBJ.MousePressed(X,Y:byte):boolean;
  1379. {}
  1380. var 
  1381.   NewItem:byte;
  1382.   Sub: BaseMenuPtr;
  1383. begin
  1384.    NewItem := TargetPick(X,Y);
  1385.    if (NewItem <> 0) then
  1386.    begin
  1387.       Sub := ItemPtr(vActiveItem)^.SubMenu;
  1388.       if (NewItem <> vActiveItem) then
  1389.       begin
  1390.          if vMenuDown and (Sub <> nil) then
  1391.                Sub^.Remove;
  1392.          ChangeActiveItem(NewItem);
  1393.       end
  1394.       else if vMenuDown and (Sub <> nil) and (Sub^.GetPickOff = false) then {turn off sub pick}
  1395.       begin
  1396.            Sub^.TurnPickOff;
  1397.            ChangeMessage(vActiveItem,true);
  1398.       end;
  1399.       MousePressed := true;
  1400.    end   
  1401.    else
  1402.       MousePressed := false;
  1403. end; {PullMenuOBJ.MousePressed}
  1404.  
  1405. function PullMenuOBJ.ProcessKey(K:word; X,Y:byte):word;
  1406. {}
  1407. var
  1408.    Choice : word;
  1409.    Sub: BaseMenuPtr;
  1410.    Hotkey, L,C,R,Temp: boolean;
  1411.    LastActiveItem : byte;
  1412. begin
  1413.    Hotkey := false;
  1414.    Choice := AltHKItem(K);
  1415.    LastActiveItem := vActiveItem;
  1416.    {HotKeyHook}
  1417.    Sub := ItemPtr(vActiveItem)^.SubMenu;
  1418.    if Choice <> 0 then
  1419.    begin
  1420.       if (Choice <> vActiveItem) then
  1421.       begin
  1422.          if vMenuDown and (Sub <> nil) then
  1423.             Sub^.Remove;
  1424.          ChangeActiveItem(Choice);
  1425.       end;
  1426.       Sub := ItemPtr(vActiveItem)^.SubMenu;
  1427.       if Sub <> nil then
  1428.       begin
  1429.          Choice := 0;
  1430.          vMenuDown := true;
  1431.          vSubActive := true;
  1432.       end
  1433.       else
  1434.       begin
  1435.          Choice := GetID(vActiveItem);
  1436.          if Choice = 0 then
  1437.             Choice := vActiveItem;
  1438.       end;
  1439.    end
  1440.    else     {no hotkey pressed}
  1441.    begin
  1442.       if (K = 513) and (TargetPick(X,Y) <> 0) then
  1443.       begin
  1444.          vMenuDown := true;
  1445.          vSubActive := true;
  1446.          if not vMsgVisible then
  1447.             ChangeMessage(vActiveItem,true);
  1448.       end;
  1449.       if Sub = nil then
  1450.          vSubActive := false
  1451.       else if vMenuDown then
  1452.          vSubActive := true;
  1453.       if (vSubActive) then
  1454.       begin
  1455.          if (K <> 513) then
  1456.          begin
  1457.             Choice := Sub^.ProcessKey(K,X,Y);
  1458.             if Choice = LeftID then
  1459.             begin
  1460.                MoveLeft;
  1461.                Choice := 0;
  1462.             end
  1463.             else if choice = RightID then
  1464.             begin
  1465.                MoveRight;
  1466.                Choice := 0;
  1467.             end
  1468.          end
  1469.          else {if (K=513) then }
  1470.          begin
  1471.             if Sub^.MenuZone(X,Y) then
  1472.             begin
  1473.                {clear main message}
  1474.                ChangeMessage(vActiveItem,false);
  1475.                Choice := Sub^.ProcessKey(K,X,Y)
  1476.             end
  1477.             else
  1478.             begin
  1479.                Temp := MousePressed(X,Y);
  1480.                if not Temp then
  1481.                begin
  1482.                   Mouse.Status(L,C,R,X,Y);
  1483.                   if not L then
  1484.                      Choice := EscapeID
  1485.                   else
  1486.                      ChangeMessage(VActiveItem,true);
  1487.                end;
  1488.             end;
  1489.          end;
  1490.       end
  1491.       else  {not sub active}
  1492.       begin
  1493.          if HotKeySelect(K) then
  1494.             HotKey := true
  1495.          else
  1496.          begin
  1497.             case K of
  1498.                513: Temp := MousePressed(X,Y);
  1499.                331: MoveLeft;
  1500.                333: MoveRight;
  1501.                327: MoveHome;
  1502.                335: MoveEnd;
  1503.             end; {case}
  1504.          end;
  1505.          if ((K= 27) and vAllowEsc) then
  1506.             Choice := EscapeID
  1507.          else if HotKey or (K = 13) or (K=513) then
  1508.          begin
  1509.             if Sub <> nil then
  1510.             begin
  1511.                vMenuDown := true;
  1512.                Sub^.DrawEngine(pred(Screen.WhereX),succ(Screen.WhereY));
  1513.                if K = 13 then
  1514.                   vSubActive := true
  1515.                else
  1516.                   vSubActive := false;
  1517.             end
  1518.             else
  1519.             begin
  1520.                Mouse.Status(L,C,R,X,Y);
  1521.                if (K = 13) or ((K=513) and (L=false)) then
  1522.                begin
  1523.                   Choice := GetID(vActiveItem);
  1524.                   if Choice = 0 then
  1525.                      Choice := vActiveItem;
  1526.                end;
  1527.             end;
  1528.          end;
  1529.       end;
  1530.    end;
  1531.    Sub := ItemPtr(vActiveItem)^.SubMenu;
  1532.    if vMenuDown and (Sub <> nil) then
  1533.    begin
  1534.       if (LastActiveItem <> vActiveItem) and (K<> 513) then
  1535.          ChangeMessage(vActiveItem,false);
  1536.       Sub^.DrawEngine(pred(Screen.WhereX),succ(Screen.WhereY));
  1537.    end;
  1538.    if (K = 513) then
  1539.    begin
  1540.       Mouse.Status(L,C,R,X,Y);
  1541.       if not L then
  1542.       begin
  1543.          if (Sub <> nil) and (Sub^.GetSubActive = false) then
  1544.          begin
  1545.             ChangeMessage(vActiveItem,false);
  1546.             Sub^.DisplayItem(Sub^.GetActiveItem,true,true);
  1547.          end;
  1548.       end;
  1549.    end;
  1550.    ProcessKey := Choice;
  1551. end; {PullMenuOBJ.ProcessKey}
  1552.  
  1553. function PullMenuOBJ.Activate: word;         
  1554. {}
  1555. begin
  1556.    Activate := Push(0,0,0);
  1557. end; {PullMenuOBJ.Activate}
  1558.  
  1559. function PullMenuOBJ.Push(K:word; X,Y:byte): word;
  1560. {}
  1561. var
  1562.    Choice: word;
  1563.    MVisible: boolean;
  1564.    FirstIteration: boolean;
  1565.    CX,CY,CT,CB:byte;
  1566. begin
  1567.    vSubActive := false;
  1568.    vMenuDown := false;
  1569.    MVisible := Mouse.Visible;
  1570.    if Monitor^.ColorOn then
  1571.       with Screen do
  1572.       begin
  1573.          CursSave;
  1574.          CX := WhereX;
  1575.          CY := WhereY;
  1576.          CT := CursTop;
  1577.          CB := CursBot;
  1578.          CursOff;
  1579.       end;
  1580.    if not vMenuBarVisible then
  1581.       DrawEngine(0,0);
  1582.    if not MVisible then
  1583.       Mouse.Show;
  1584.    FirstIteration := true;
  1585.    repeat
  1586.       if (FirstIteration = false) or ((K=0) and (X=0) and (Y=0)) then
  1587.          with Key do
  1588.          begin
  1589.             GetInput;
  1590.             K := LastKey;
  1591.             X := LastX;
  1592.             Y := LastY;
  1593.          end;
  1594.       if (K = vHelpKey) and (vMenuDown = false) then
  1595.       begin
  1596.          HelpTask(GetHelpID);
  1597.          Choice := 0;
  1598.       end
  1599.       else 
  1600.       begin
  1601.          Choice := HotKeyID(K);
  1602.          (*
  1603.          Choice := 0;
  1604.          *)
  1605.          if Choice = 0 then
  1606.             Choice := ProcessKey(K,X,Y);
  1607.       end;
  1608.       FirstIteration := false;
  1609.    until (Choice <> 0) and (Choice <> DriftID);
  1610.    if Choice = EscapeID then
  1611.       Push := 0
  1612.    else
  1613.       Push := Choice;
  1614.    ChangeMessage(vActiveItem,false);
  1615.    if vSubActive and (ItemPtr(vActiveItem)^.SubMenu <> nil) then
  1616.       ItemPtr(vActiveItem)^.SubMenu^.Remove;
  1617.    DisplayItem(vActiveItem,false,false);
  1618.    vLastKey := Key.LastKey;
  1619.    if not MVisible then
  1620.       Mouse.Hide;
  1621.    if Monitor^.ColorOn then
  1622.       with Screen do
  1623.       begin
  1624.          GotoXY(CX,CY);
  1625.          CursSize(CT,CB);
  1626.       end;
  1627. end; {PullMenuOBJ.Push}
  1628.  
  1629. destructor PullMenuOBJ.Done;
  1630. {}
  1631. begin
  1632.    LotusMenuOBJ.Done;
  1633. end; {PullMenuOBJ.Done}
  1634. {|||||||||||||||||||||||||||||||||||||||||||}
  1635. {                                           }
  1636. {     E Z P u l l O B J   M E T H O D S     }
  1637. {                                           }
  1638. {|||||||||||||||||||||||||||||||||||||||||||}
  1639. constructor EZPullOBJ.Init;
  1640. {}
  1641. begin
  1642.    new(vTopBar,Init);
  1643.    vSubMenuStack := nil;
  1644.    vListAssigned := false;
  1645.    vTotalSubs := 0;
  1646. end; {EZPullOBJ.Init}
  1647.  
  1648. function EZPullOBJ.MainMenu:pPullMenuOBJ;
  1649. {}
  1650. begin
  1651.    MainMenu := vTopBar;
  1652. end; {EZPullOBJ.MainMenu}
  1653.  
  1654. function EZPullOBJ.SubMenu(MenuNumber: byte):SubMenuPtr;
  1655. {}
  1656. var 
  1657.   Temp: SubMenuListPtr;
  1658.   I : integer;
  1659. begin
  1660.    if (MenuNumber < 1) or (MenuNumber > vTotalSubs) then
  1661.       Submenu := nil
  1662.    else
  1663.    begin
  1664.       Temp := vSubMenuStack;
  1665.       for I := 2 to MenuNumber do
  1666.          if Temp <> nil then
  1667.             Temp := Temp^.NextMenu;
  1668.       SubMenu := Temp^.SubMenu;
  1669.    end;
  1670. end; {EZPullOBJ.SubMenu}
  1671.  
  1672. function EZPullOBJ.Activate: word;       
  1673. {}
  1674. begin
  1675.    if vListAssigned = false then
  1676.       Activate := 0
  1677.    else
  1678.       Activate := MainMenu^.Activate;
  1679. end; {EZPullOBJ.Activate}
  1680.  
  1681. function EZPullOBJ.Push(K:word; X,Y:byte): word;       
  1682. {}
  1683. begin
  1684.    if vListAssigned = false then
  1685.       Push := 0
  1686.    else
  1687.       Push := MainMenu^.Push(K,X,Y);
  1688. end; {EZPullOBJ.Activate}
  1689.  
  1690. procedure EZPullOBJ.BuildMenu;
  1691. {}
  1692. var
  1693.    Txt: StrVisible;
  1694.    Msg: StrVisible;
  1695.    HK: word;
  1696.    SpecialHK: word;
  1697.    ID: word;
  1698.    Active: boolean;
  1699.    I: integer;
  1700.  
  1701.    procedure ParseItemInfo(Str:String;BakID:word);
  1702.    {}
  1703.    var 
  1704.       P : byte;
  1705.       IDStr: StrVisible;
  1706.    begin
  1707.       Txt := '';
  1708.       Msg := '';
  1709.       HK := 0;
  1710.       SpecialHK := 0;
  1711.       Active := true;
  1712.       P := pos(EZSeparator,Str);
  1713.       if P = 0 then
  1714.          Txt := Str
  1715.       else
  1716.       begin
  1717.          Txt := copy(Str,1,pred(p));
  1718.          Msg := copy(Str,succ(P),255);
  1719.          P := pos(EZSeparator,Msg);
  1720.          if P <> 0 then
  1721.          begin
  1722.             IDStr := copy(Msg,succ(P),255);
  1723.             delete(Msg,P,255);
  1724.             P := pos(EZSeparator,IDStr);
  1725.             if P = 0 then
  1726.                ID := StrToInt(IDStr)
  1727.             else
  1728.             begin
  1729.                ID := StrtoInt(copy(IDStr,1,pred(P)));
  1730.                SpecialHK := StrtoInt(copy(IDStr,succ(P),255));
  1731.             end;
  1732.          end
  1733.          else
  1734.             ID := BakID;
  1735.       end;
  1736.       if (Txt <> '') and (Txt[1] = EZInActive) then
  1737.       begin
  1738.          Active := false;
  1739.          delete(Txt,1,1);
  1740.       end;
  1741.       P := pos(Screen.HiMarker,Txt);
  1742.       if P <> 0 then
  1743.          HK := ord(upcase(Txt[succ(p)]));
  1744.    end; {ParseItemInfo}
  1745.  
  1746.    procedure BuildMenuBar;
  1747.    {}
  1748.    var 
  1749.      Str:string;
  1750.      I : integer;
  1751.    begin
  1752.       Str := GetString(1);
  1753.       if (Str = '') then
  1754.          Str := 'Guess';
  1755.       if (Str[1] = EZNewBarItem) then
  1756.          delete(Str,1,1);
  1757.       ParseItemInfo(Str,1);
  1758.       Mainmenu^.AddFullItem(Txt,ID,HK,Msg,nil);
  1759.       if SpecialHK <> 0 then
  1760.          Mainmenu^.SetSpecialKey(SpecialHK,ID);
  1761.       if not Active then
  1762.          Mainmenu^.SetStatus(1,false);
  1763.       inc(vTotalSubs);  
  1764.       for I := 2 to TotalStrings do
  1765.       begin
  1766.          Str := GetString(I);
  1767.          if (Str <> '') and (Str[1] = EZNewBarItem) then
  1768.          begin
  1769.             delete(Str,1,1);
  1770.             ParseItemInfo(Str,I);
  1771.             Mainmenu^.AddFullItem(Txt,ID,HK,Msg,nil);
  1772.             if SpecialHK <> 0 then
  1773.                Mainmenu^.SetSpecialKey(SpecialHK,ID);
  1774.             if not Active then
  1775.                Mainmenu^.SetStatus(I,false);
  1776.             inc(vTotalSubs);  
  1777.          end;
  1778.       end;
  1779.    end; {BuildMenuBar}
  1780.  
  1781.    procedure BuildSubMenuList;
  1782.    {}
  1783.    var 
  1784.      I: integer;
  1785.      Temp: SubMenuListPtr; 
  1786.    begin
  1787.       if MemAvail < vTotalSubs*sizeof(SubMenuList) then
  1788.          Error(1)
  1789.       else
  1790.       begin
  1791.          getmem(vSubMenuStack,sizeof(vSubMenuStack^));
  1792.          vSubMenuStack^.NextMenu := nil;
  1793.          vSubMenuStack^.SubMenu := nil;
  1794.          Temp := vSubMenuStack;
  1795.          for I := 2 to vTotalSubs do
  1796.          begin
  1797.             getmem(Temp^.NextMenu,sizeof(vSubMenuStack^));
  1798.             Temp := Temp^.Nextmenu;
  1799.             Temp^.SubMenu := nil;
  1800.          end;
  1801.          Temp^.NextMenu := nil;
  1802.       end;
  1803.    end; {BuildSubMenuList}
  1804.  
  1805.    procedure CreateSubMenu(SubCounter:byte);
  1806.    {}
  1807.    var 
  1808.       Temp: SubMenuListPtr;
  1809.       I : integer;
  1810.    begin
  1811.       Temp := vSubMenuStack;
  1812.       for I := 2 to SubCounter do
  1813.           Temp := Temp^.NextMenu;
  1814.       new(Temp^.Submenu,Init);
  1815.       Temp^.Submenu^.SetForPull;
  1816.    end; {CreateSubMenu}
  1817.  
  1818.    procedure BuildSubMenus;
  1819.    {}
  1820.    var 
  1821.      Str:string;
  1822.      I : integer;
  1823.      SubCreated: boolean;
  1824.      SubCounter: byte;
  1825.      PickCounter : byte;
  1826.    begin
  1827.       SubCreated := false;
  1828.       SubCounter := 1;
  1829.       for I := 2 to TotalStrings do
  1830.       begin
  1831.          Str := GetString(I);
  1832.          if (Str <> '') then
  1833.          begin
  1834.             if (Str[1] = EZNewBarItem) then
  1835.             begin
  1836.                with SubMenu(SubCounter)^ do
  1837.                   SetActiveItem(FirstActiveItem);
  1838.                SubCreated := false;
  1839.                inc(SubCounter);
  1840.             end
  1841.             else
  1842.             begin
  1843.                if not SubCreated then
  1844.                begin
  1845.                   SubCreated := true;
  1846.                   CreateSubMenu(SubCounter);
  1847.                   PickCounter := 0;
  1848.                end;
  1849.                ParseItemInfo(Str,I);
  1850.                SubMenu(SubCounter)^.AddFullItem(Txt,ID,HK,Msg,nil);
  1851.                inc(PickCounter);
  1852.                if SpecialHK <> 0 then
  1853.                   Mainmenu^.SetSpecialKey(SpecialHK,ID);
  1854.                if not Active then
  1855.                   SubMenu(SubCounter)^.SetStatus(PickCounter,false);
  1856.             end;
  1857.          end;
  1858.       end;
  1859.    end; {BuildSubMenus}
  1860.  
  1861. begin
  1862.    BuildMenuBar;
  1863.    BuildSubMenuList;
  1864.    BuildSubMenus;
  1865.    for I := 1 to  vTotalSubs do
  1866.       if SubMenu(I) <> nil then
  1867.          Mainmenu^.SetSubMenu(I,SubMenu(I));
  1868. end; {EZPullOBJ.BuildMenu}
  1869.  
  1870. function EZPullOBJ.GetString(Item: word):string;
  1871. {abstract}
  1872. begin
  1873.    GetString := '';
  1874. end; {EZPullOBJ.GetString}
  1875.  
  1876. function EZPullOBJ.TotalStrings: word;
  1877. {abstract} 
  1878. begin 
  1879.    TotalStrings := 0;
  1880. end; {EZPullOBJ.TotalStrings}
  1881.  
  1882. destructor EZPullOBJ.Done;                 
  1883. {}
  1884. var 
  1885.   Temp: SubMenuListPtr;
  1886.   I: integer;
  1887. begin
  1888.    for I := 1 to vTotalSubs do
  1889.    begin
  1890.       Temp := vSubMenuStack;
  1891.       while (Temp <> nil) and (Temp^.NextMenu <> nil) do
  1892.          Temp := Temp^.NextMenu;
  1893.       if (Temp <> nil) and (Temp^.SubMenu <> nil) then
  1894.       begin
  1895.          Dispose(Temp^.SubMenu,Done);
  1896.          Temp^.Submenu := nil;
  1897.       end;
  1898.       if Temp^.NextMenu <> nil then
  1899.       begin
  1900.          freemem(Temp^.NextMenu,sizeof(Temp^.NextMenu^));
  1901.          Temp^.NextMenu := nil;
  1902.       end;
  1903.    end;
  1904.    if Temp <> nil then
  1905.    begin
  1906.       if Temp^.SubMenu <> nil then
  1907.          Dispose(Temp^.SubMenu,Done);
  1908.       freemem(Temp,sizeof(Temp^));
  1909.    end;
  1910.    dispose(vTopBar,Done);
  1911. end; {EZPullOBJ.Done}
  1912. {|||||||||||||||||||||||||||||||||||||||||||||||||||||}
  1913. {                                                     }
  1914. {     E Z P u l l A r r a y O B J   M E T H O D S     }
  1915. {                                                     }
  1916. {|||||||||||||||||||||||||||||||||||||||||||||||||||||}
  1917. constructor EZPullArrayOBJ.Init;
  1918. {}
  1919. begin
  1920.    EZPullOBJ.Init;
  1921. end; {EZPullArrayOBJ.Init}
  1922.  
  1923. procedure EZPullArrayOBJ.AssignList(var StrArray; Total:Longint; StrLength:byte);
  1924. {}
  1925. begin
  1926.    vArrayPtr := @StrArray;
  1927.    vStrLength := StrLength;
  1928.    vTotalItems := Total;
  1929.    vListAssigned := true;
  1930.    BuildMenu;
  1931. end; {EZPullArrayOBJ.AssignList}
  1932.  
  1933. function EZPullArrayOBJ.TotalStrings: word;                               
  1934. {}
  1935. begin
  1936.    TotalStrings := vTotalItems;
  1937. end; {EZPullArrayOBJ.TotalStrings}
  1938.  
  1939. function EZPullArrayOBJ.GetString(Item: word): string;                    
  1940. {}
  1941. var
  1942.   W : longint;
  1943.   TempStr : String;
  1944.   ArrayOffset: word;
  1945. begin
  1946.    {move array string to Temp}
  1947.    W := pred(Item) * succ(vStrLength);
  1948.    ArrayOffset := Ofs(vArrayPtr^) + W;
  1949.    Move(Mem[Seg(vArrayPtr^):ArrayOffset],TempStr,1);
  1950.    Move(Mem[Seg(vArrayPtr^):succ(ArrayOffset)],TempStr[1],ord(TempStr[0]));
  1951.    GetString := TempStr;
  1952. end; {EZPullArrayOBJ.GetString}
  1953.  
  1954. destructor EZPullArrayOBJ.Done;
  1955. {}
  1956. begin
  1957.    EZPullOBJ.Done;
  1958. end; {EZPullArrayOBJ.Done}
  1959. {|||||||||||||||||||||||||||||||||||||||||||||||||||}
  1960. {                                                   }
  1961. {     E Z P u l l L i n k O B J   M E T H O D S     }
  1962. {                                                   }
  1963. {|||||||||||||||||||||||||||||||||||||||||||||||||||}
  1964. constructor EZPullLinkOBJ.Init;
  1965. {}
  1966. begin
  1967.    EZPullOBJ.Init;
  1968. end; {EZPullLinkOBJ.Init}
  1969.  
  1970. procedure EZPullLinkOBJ.AssignList(var LinkList: DLLOBJ);
  1971. {}
  1972. begin
  1973.    vLinkList := @LinkList;
  1974.    vListAssigned := true;
  1975.    BuildMenu;
  1976. end; {EZPullLinkOBJ.AssignList}
  1977.  
  1978. function EZPullLinkOBJ.TotalStrings: word;              
  1979. {}
  1980. begin
  1981.    TotalStrings := vLinkList^.TotalNodes;
  1982. end; {EZPullLinkOBJ.TotalStrings}
  1983.  
  1984. function EZPullLinkOBJ.GetString(Item: word): string;   
  1985. {}
  1986. var TempPtr : DLLNodePtr;
  1987. begin
  1988.    TempPtr := vLinkList^.NodePtr(Item);
  1989.    if TempPtr <> Nil then
  1990.       vLinkList^.ShiftActiveNode(TempPtr,Item);
  1991.    GetString := vLinkList^.GetStr(TempPtr,0,255);
  1992. end; {EZPullLinkOBJ.GetString}
  1993.  
  1994. destructor EZPullLinkOBJ.Done;                            
  1995. {}
  1996. begin
  1997.    EZPullOBJ.Done;
  1998. end; {EZPullLinkOBJ.Done}
  1999. {|||||||||||||||||||||||||||||||||||||||||||||||}
  2000. {                                               }
  2001. {     U N I T   I N I T I A L I Z A T I O N     }
  2002. {                                               }
  2003. {|||||||||||||||||||||||||||||||||||||||||||||||}
  2004. procedure MenuInit;
  2005. {initilizes objects and global variables}
  2006. begin
  2007. end; {MenuInit}
  2008.  
  2009. {end of unit - add intialization routines below}
  2010. {$IFNDEF OVERLAY}
  2011. begin
  2012.    MenuInit;
  2013. {$ENDIF}
  2014. end.
  2015.  
  2016.  
  2017.